package org.wattdepot.cli.command;

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import org.wattdepot.client.BadXmlException;
import org.wattdepot.client.MiscClientException;
import org.wattdepot.client.NotAuthorizedException;
import org.wattdepot.client.ResourceNotFoundException;
import org.wattdepot.client.WattDepotClient;
import org.wattdepot.resource.property.jaxb.Property;
import org.wattdepot.resource.source.jaxb.Source;
import org.wattdepot.resource.source.summary.jaxb.SourceSummary;
import org.wattdepot.util.UriUtils;

/**
 * Implements the ListSummaryCommand handler.
 * 
 * @author Yichi Xu
 *
 */
public class SummaryCommand extends WattDepotCliCommand {

  /**
   * Creates an instance of the ListSummaryCommand command handler.
   * 
   * @param client An instance of the WattDepotClient.
   */
  public SummaryCommand(WattDepotClient client) {
    super(client);
  }

  /**
   * Performs the command.
   * @param command The command to process.
   * @return The result of the command.
   */
  @Override
  public String doCommand(String command) {
    StringTokenizer tokenizer = new StringTokenizer(command);
    List<String> tokens = new ArrayList<String>();
    while (tokenizer.hasMoreTokens()) {
      tokens.add(tokenizer.nextToken());
    }

    if (!"summary".equals(tokens.get(0))) {
      return WattDepotCliCommand.reportUnknownCommand(command);
    }
    
    if (tokens.size() != 2) {
      return this.reportError(PARAMETER_COUNT_ERROR);
    }
    
    try {
      return this.listSummary(tokens.get(1));
    }
    catch (ResourceNotFoundException ex) {
      return this.reportError(SOURCE_ERROR + tokens.get(1));
    }
    catch (BadXmlException ex) {
      return this.reportError(BAD_XML_ERROR);
    }
    catch (Exception ex) {
      return this.reportError(CONNECTION_ERROR);
    }
  }

  /**
   * List the summary of a specified source given the name of the source.
   * 
   * @param sourceName The name of the source to be summarized.
   * @throws MiscClientException Exception
   * @throws BadXmlException Exception
   * @throws ResourceNotFoundException Exception
   * @throws NotAuthorizedException Exception
   * @return message that contains the summary
   */
  private String listSummary(String sourceName) throws NotAuthorizedException,
      ResourceNotFoundException, BadXmlException, MiscClientException {
    Source source = client.getSource(sourceName);
    String format = " %1$s: %2$s \n";
    StringBuffer buf = new StringBuffer();
    StringBuffer subSources = new StringBuffer();
    if (source.getSubSources() != null) {
      for (String href : source.getSubSources().getHref()) {
        subSources.append(UriUtils.getUriSuffix(href));
        subSources.append(", ");
      }
    }
    String subSourcesString = subSources.toString();
    
    if (subSourcesString.length() > 2) {
      subSourcesString = subSourcesString.substring(0, subSourcesString.length() - 2);
    }
    
    buf.append(String.format(format, "SubSources", subSourcesString));
    buf.append(String.format(format, "Description", source.getDescription()));
    String owner = UriUtils.getUriSuffix(source.getOwner());
    
    buf.append(String.format(format, "Owner", owner));
    buf.append(String.format(format, "Location", source.getLocation()));
    buf.append(String.format(format, "Coordinates", source.getCoordinates()));
    StringBuffer propertyBuf = new StringBuffer();
    
    if (source.isSetProperties()) {
      for (Property property : source.getProperties().getProperty()) {
        propertyBuf.append('(');
        propertyBuf.append(property.getKey());
        propertyBuf.append(" : ");
        propertyBuf.append(property.getValue());
        propertyBuf.append("), ");
      }
      propertyBuf.delete(propertyBuf.length() - 2, propertyBuf.length());
    }
    
    String propertyString = propertyBuf.toString();
    buf.append(String.format(format, "Properties", propertyString));
    SourceSummary sourceSummary = client.getSourceSummary(sourceName);
    buf.append(String.format(format, "Earliest data", 
        sourceSummary.getFirstSensorData().toString()));
    buf.append(String.format(format, "Latest data", sourceSummary.getLastSensorData().toString()));
    buf.append(String.format(format, "Total data points", sourceSummary.getTotalSensorDatas())); 
    
    return buf.toString();
  }
  
  /**
   * Gets the help string associated with the summary command.
   * 
   * @see org.wattdepot.cli.command.WattDepotCliCommand#getHelp()
   * @return Information on how to invoke the summary command.
   */
  @Override
  public String getHelp() {
    return "summary {source}\n"
      + "  Prints information about a single source.\n";
  }
}
